/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2025-04-01     金鹏       the first version
 */
#include "syn6288.h"

extern struct CMN_UART uart_device[6];              /* 串口设备表 */
extern short len;                                   /* 语音唯一长度*/
static rt_thread_t syn6288_handl = RT_NULL;         /* 语音合成模块线程句柄*/

/*
 * SYN6288_Sent
 * @Param NULL
 *
 * Change Logs:
 * Date        Author       Notes
 * 2025-4-1     金鹏        串口4发送
 */
static void SYN6288_Sent(unsigned char buff[],short len)
{
    for(int i=0; i<len; i++){
        rt_device_write(uart_device[3].uart_serial,0,&buff[i],1);
    }
}

/*
 * SYN6288_SendFrameInfo
 * @Param NULL
 *
 * Change Logs:
 * Date        Author       Notes
 * 2025-4-1     金鹏        语音合成帧播报
 */
static void SYN6288_SendFrameInfo(unsigned char Music, unsigned char *HZdata,int length)
{
    /****************需要发送的文本**********************************/
    unsigned  char  Frame_Info[150];
    unsigned  char  HZ_Length;
    unsigned  char  ecc  = 0;             //定义校验字节
    unsigned  int i = 0;

    HZ_Length = length;           //需要发送文本的长度

    /*****************帧固定配置信息**************************************/
    Frame_Info[0] = 0xFD ;                //构造帧头FD
    Frame_Info[1] = 0x00 ;                //构造数据区长度的高字节
    Frame_Info[2] = HZ_Length + 3;        //构造数据区长度的低字节
    Frame_Info[3] = 0x01 ;                //构造命令字：合成播放命令
    Frame_Info[4] = 0x03 | Music << 4 ;   //构造命令参数：背景音乐设定

    /*******************校验码计算***************************************/
    for (i = 0; i < 5; i++)               //依次发送构造好的5个帧头字节
        ecc = ecc ^ (Frame_Info[i]);      //对发送的字节进行异或校验

    for (i = 0; i < HZ_Length; i++)       //依次发送待合成的文本数据
        ecc = ecc ^ (HZdata[i]);          //对发送的字节进行异或校验
    /*******************发送帧信息***************************************/
    memcpy(&Frame_Info[5], HZdata, HZ_Length);

    Frame_Info[5 + HZ_Length] = ecc;
//    for(int i=0;i<5 + HZ_Length + 1;i++){
//        rt_kprintf("%x\n",Frame_Info[i]);
//    }
    SYN6288_Sent(Frame_Info,5 + HZ_Length + 1);
}

/*
 * SYN6288_Say
 * @Param NULL
 *
 * Change Logs:
 * Date       Author        Notes
 * 2025-4-1     金鹏        语音合成播报
 */
static void SYN6288_Say(unsigned char *fmt, int length)
{

    SYN6288_SendFrameInfo(0, fmt, length);     // 无背景音?
}

/*
 * SYN6288_Say_UTF8
 * @Param NULL
 *
 * Change Logs:
 * Date       Author        Notes
 * 2025-4-1     金鹏        语音合成播报(UTF-8)
 */
void SYN6288_Say_UTF8(unsigned char *cmd)
{
    unsigned char* respon_utf8 = cmd;
    unsigned char respon_uni[150] = "";

    /* UTF8 -> Unicode*/
    len = utf8_to_unicode(respon_utf8,respon_uni);

    if(rt_mq_send(voice_recv_mq, respon_uni, len) != RT_EOK){
        rt_kprintf("say failed!!\n");
    }
}

/*
 * SYN6288_Recv_Init
 * @Param NULL
 *
 * Change Logs:
 * Date        Author      Notes
 * 2025-1-11     金鹏   语音合成消息队列初始化
 */
static ENTRY SYN6288_Recv_Init(void)
{
    /* 创建wifi接收消息队列*/
    voice_recv_mq = rt_mq_create("voice",
        MQ_STACK_SIZE+100,
             MQ_COUNT-10,
              MQ_FLAG);

    if(voice_recv_mq == RT_NULL){
        rt_kprintf("voice recv mq create failed\n");
        return -RT_ERROR;
    }else{
        rt_kprintf("voice recv mq create successed\n");
    }

    return RT_EOK;
}

/*
 * SYN6288_Entry
 * @Param NULL
 *
 * Change Logs:
 * Date        Author        Notes
 * 2025-4-1     金鹏        语音合成模块线程
 */
void SYN6288_Entry(void *parameter)
{
    unsigned char buff[150] = "";

    while(1){
        if(rt_mq_recv(voice_recv_mq, buff, sizeof(buff), MQ_WAIT_FLAG) == RT_EOK){

            SYN6288_Say(buff,len);

        }
    }
}

/*
 * M100P_Test
 * @Param NULL
 *
 * Change Logs:
 * Date        Author       Notes
 * 2025-4-1     金鹏        语音合成模块测试
 */
ENTRY SYN6288_Test(void)
{
    /* 语音合成初始化*/
    if( CMN_Uart_Init("uart4") != RT_EOK){
        rt_kprintf("SYN6288_Init failed\n");
        return -RT_ERROR;
    }else{
        rt_kprintf("SYN6288_Init Successful\n");
    }

    /* 语音合成消息队列初始化*/
    if( SYN6288_Recv_Init() != RT_EOK){
        rt_kprintf("SYN6288_Mq failed\n");
        return -RT_ERROR;
    }else{
        rt_kprintf("SYN6288_Mq Successful\n");
    }

    /* 创建语音合成模块线程*/
    syn6288_handl = rt_thread_create("syn6288",
        SYN6288_Entry,RT_NULL,
        ENTRY_STACK_SIZE,
        ENTRY_PRI,
        ENTRY_TICK);

    /* LOG*/
    if(syn6288_handl != RT_NULL){
        rt_kprintf("syn6288 thread create successful!!\n");

        /* 启动4G模块线程*/
        rt_thread_startup(syn6288_handl);
    }else{
        rt_kprintf("syn6288 thread create failed!!\n");

        return -RT_ERROR;
    }
}
